package org.jsola.hr.service.impl;

import com.alibaba.fastjson.JSON;
import org.jsola.common.DateKit8;
import org.jsola.hr.constant.PunchType;
import org.jsola.hr.dto.attendschedule.AttendPeriodDTO;
import org.jsola.hr.entity.AttendPlanDO;
import org.jsola.hr.entity.AttendPunchRecordDO;
import org.jsola.hr.entity.AttendPunchTimeDO;
import org.jsola.hr.entity.EmpInfoDO;
import org.jsola.hr.exception.HrException;
import org.jsola.hr.query.AttendPunchRecordQuery;
import org.jsola.hr.query.AttendPunchTimeQuery;
import org.jsola.hr.query.EmpInfoQuery;
import org.jsola.hr.query.PunchRecordQuery;
import org.jsola.hr.service.*;
import org.jsola.hr.vo.AttendNeedPunchVO;
import org.jsola.hr.vo.PunchRecordVO;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author wxz
 */
@Service("hrAttendPunchAppStatServiceImpl")
public class AttendPunchAppStatServiceImpl implements IAttendPunchAppStatService {

    @Autowired
    private IEmpInfoService empInfoService;
    @Autowired
    private IAttendPlanService attendPlanService;
    @Autowired
    private IAttendPunchTimeService attendPunchTimeService;
    @Autowired
    private IAttendPunchRecordService attendPunchRecordService;
    @Autowired
    private IAttendCalendarService attendCalendarService;

    @Override
    public List<PunchRecordVO> selectPunchRecord(PunchRecordQuery punchRecordQuery, TokenUser tokenUser) {
        List<PunchRecordVO> result = new ArrayList<>();
        // 查询员工信息
        EmpInfoQuery empInfoQuery = new EmpInfoQuery();
        empInfoQuery.setUserId(tokenUser.getUserId());
        List<EmpInfoDO> empInfoList = empInfoService.selectDO(empInfoQuery, tokenUser);
        if (empInfoList.size() <= 0) {
            throw new HrException("用户信息不存在");
        }

        EmpInfoDO empInfoDO = empInfoList.get(0);

        // 查询上班下班打卡记录
        AttendPunchRecordQuery attendPunchRecordQuery = new AttendPunchRecordQuery();
        attendPunchRecordQuery.setYear(punchRecordQuery.getDateYmd().split("-")[0]);
        attendPunchRecordQuery.setMonth(punchRecordQuery.getDateYmd().split("-")[1]);
        attendPunchRecordQuery.setDay(punchRecordQuery.getDateYmd().split("-")[2]);
        attendPunchRecordQuery.setEmpInfoId(empInfoDO.getId());
        attendPunchRecordQuery.addOrder("punchTime", false);
        List<AttendPunchRecordDO> attendPunchRecordList = attendPunchRecordService.selectDO(attendPunchRecordQuery, tokenUser.getSiteId());

        // 查询当前用户使用的考勤规则
        AttendPlanDO attendPlanDO = null;
        List<AttendPlanDO> attendPlanDOList = attendPlanService.getAttendPlan(empInfoDO.getId(), punchRecordQuery.getDateYmd(), tokenUser.getSiteId());
        if (attendPlanDOList == null) {
            throw new HrException("未设置考勤规则");
        } else {
            attendPlanDO = attendPlanDOList.get(0);
        }

        // 查询考勤打卡时间
        AttendPunchTimeQuery attendPunchTimeQuery = new AttendPunchTimeQuery();
        attendPunchTimeQuery.setAttendPlanId(attendPlanDO.getId());
        List<AttendPunchTimeDO> attendPunchTimeList = attendPunchTimeService.selectDO(attendPunchTimeQuery, tokenUser.getSiteId());
        AttendPunchTimeDO attendPunchTimeDO = null;
        String startPeriod = "";
        String endPeriod = "";
        if (CollectionUtils.isEmpty(attendPunchTimeList)) {
            throw new HrException("未设置考勤打卡时间");
        } else {
            attendPunchTimeDO = attendPunchTimeList.get(0);
        }
        List<AttendPeriodDTO> attendPeriodDTOList;

        // 当前日期是否需要打卡
        AttendNeedPunchVO attendNeedPunchVO = attendCalendarService.isNeedPunchOfDaily(attendPlanDO.getId(), punchRecordQuery.getDateYmd(), tokenUser.getSiteId());
        if (attendNeedPunchVO.getIsSpecialDate()) {
            if (attendNeedPunchVO.getIsNeedPunchOfDaily()) {
                // 如果是特殊日期需要打卡，则使用特殊日期的时间设置
                attendPeriodDTOList = attendPunchTimeService
                        .puncheTimeForSpecial(attendPlanDO.getId(), punchRecordQuery.getDateYmd(), tokenUser)
                        .getPeriodList();
            } else {
                // 不需要打卡返回空的List
                return new ArrayList<>();
            }
        } else {
            // 不是特殊日期则使用普通的时间段
            attendPeriodDTOList = JSON.parseArray(attendPunchTimeDO.getPeriodJson(), AttendPeriodDTO.class);
        }

        if (CollectionUtils.isEmpty(attendPeriodDTOList)) {
            throw new HrException("未设置考勤打卡时间");
        }
        for (AttendPeriodDTO attendPeriodDTO : attendPeriodDTOList) {
            PunchRecordVO punchRecordVO = new PunchRecordVO();
            punchRecordVO.setDateYmd(punchRecordQuery.getDateYmd());
            startPeriod = attendPeriodDTO.getStartPeriod();
            endPeriod = attendPeriodDTO.getEndPeriod();
            AttendPunchRecordDO onAttendPunchRecordDO = null;
            AttendPunchRecordDO offAttendPunchRecordDO = null;
            if (!CollectionUtils.isEmpty(attendPunchRecordList)) {
                // 存在时间段内的打卡记录
                for (AttendPunchRecordDO attendPunchRecordDO : attendPunchRecordList) {
                    Date standardTime = attendPunchRecordDO.getStandardTime();
                    String format = DateKit8.format(standardTime, "HH:mm");
                    if (PunchType.ON_WORK.getValue().equals(attendPunchRecordDO.getPunchType()) && attendPeriodDTO.getStartPeriod().equals(format)) {
                        onAttendPunchRecordDO = attendPunchRecordDO;
                    } else if (PunchType.OFF_WORK.getValue().equals(attendPunchRecordDO.getPunchType()) && attendPeriodDTO.getEndPeriod().equals(format)) {
                        offAttendPunchRecordDO = attendPunchRecordDO;
                    }
                }
            }
            punchRecordVO.setStartPeriod(startPeriod);
            punchRecordVO.setEndPeriod(endPeriod);
            punchRecordVO.setOnAttendPunchRecordDO(onAttendPunchRecordDO);
            punchRecordVO.setOffAttendPunchRecordDO(offAttendPunchRecordDO);
            result.add(punchRecordVO);
        }

        return result;
    }
}
